package com.example.ccj.u.server;

import android.util.Log;


import com.example.ccj.u.ActivityUtils;
import com.example.ccj.u.LogUtils;
import com.example.ccj.u.StringUtils;
import com.example.ccj.u.ToastUtils;
import com.example.ccj.u.media.FastjsonUtil;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.OkHttpClient;

public class RequestDataHolder {
    public static String ADDRESS; //地址
    public static String PORT;//端口
    public static long connectTimeout = 5;
    public static long writeTimeout = 30;
    public static long readTimeout = 30;

//    protected static String SERVER_URL = "http://"+ ADDRESS +":"+PORT+"/";//访问地址

    private static final String TAG = "RequestDataHolder";
    int tryCount = 0;

    public RequestDataHolder(){
        if (StringUtils.isTrimEmpty(ADDRESS) || StringUtils.isTrimEmpty(PORT)) {
            ToastUtils.showShort("服务器地址或者端口号未配置，请先配置服务器地址和端口号");
            LogUtils.e("服务器地址或者端口号未配置，请先配置服务器地址和端口号");
//            throw new RuntimeException("服务器地址或者端口号未配置，请先配置服务器地址和端口号");
        }
    }

    //统一请求头
    protected static OkHttpClient getOkHttpClient(){
        //缓存容量
        int CACHE_TIMEOUT = 10 * 1024 * 1024;
        //缓存存放的文件
        File httpCacheDirectory = new File(ActivityUtils.getTopActivity().getCacheDir(), "goldze_cache");
        //缓存对象
        Cache cache = new Cache(httpCacheDirectory, CACHE_TIMEOUT);

        return new OkHttpClient.Builder()
                .addInterceptor(new HeaderInterceptor())
                .connectTimeout(connectTimeout,TimeUnit.SECONDS)
                .writeTimeout(writeTimeout, TimeUnit.SECONDS)
                .readTimeout(readTimeout, TimeUnit.SECONDS)
                .cache(cache)
//                .addInterceptor(new CacheInterceptor(ActivityUtils.getTopActivity()))
                .build();
    }

    protected Observable<Result> turnOutResult(Observable<Result> observable) {
        return observable.retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
            @Override
            public ObservableSource<?> apply(Observable<Throwable> throwableObservable)  {
                return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(Throwable throwable)  {
                        //把throwable(出错的起源)转换为observable(retryWhen的对象).
//                        throwable.printStackTrace();
//                        LogUtils.e(throwable.getMessage());
//                        for (StackTraceElement stackTraceElement : throwable.getStackTrace()) {
//                            LogUtils.e(stackTraceElement.toString());
//                        }

                        if (throwable instanceof IOException) {
                            Log.i(TAG, "io异常:"+throwable.getMessage());
                            if (tryCount < 3) {
                                tryCount++;
                                return Observable.just(1).delay(100, TimeUnit.MILLISECONDS);
                            } else {
                                tryCount = 0;
                                return Observable.error(new Throwable("连接服务器失败，重试次数"+tryCount+"->"+throwable.getMessage()));
                            }
                        } else {
                            return Observable.error(throwable);
                        }
                    }
                });
            }}).flatMap(new Function<Result, ObservableSource<Result>>() {
            @Override
            public ObservableSource<Result> apply(Result resultBean) {
                //检查返回的数据是否存在错误
                tryCount = 0;
                if (resultBean.getStatus() != 0) {
                    String error = "服务器连接错误\n错误编码：" + resultBean.getStatus() + "\n 错误信息：" + resultBean.getError();
                    if (resultBean.getMessage() != null) {
                        error += "\n错误信息："+resultBean.getMessage();
                    }
                    ToastUtils.showLong(error);
                    LogUtils.e(error);
                    return Observable.error(new Throwable(error));
                } else {
                    return Observable.just(resultBean);
                }
            }
        });
    }


    //转换为服务器返回的类
    protected Observable<Result> turnOutResultSync(Observable<Result> observable) {
        return turnOutResult(observable).subscribeOn(Schedulers.newThread());
    }

    //将服务器返回的数据转换为bean数组
    protected <T> Observable<List<T>> turnOutBeanList(Observable<Result> observable,Class<T> cls) {
        return turnOutResult(observable).map(new Function<Result, List<T>>() {
            @Override
            public List<T> apply(Result result) {
                if (cls != null && result != null && result.getData() != null) {

//                    return GsonUtils.fromJsonList(result.getData(),cls);
                    return FastjsonUtil.toListBean(result.getData(),cls);
                }
                return null;
            }
        }).subscribeOn(Schedulers.newThread());
    }


    //将服务器返回的数据转换为bean
    protected <T> Observable<T> turnOutBean(Observable<Result> observable, Class<T> cls) {
        return turnOutResult(observable).map(new Function<Result, T>() {
            @Override
            public T apply(Result result) {
                if (cls != null && result != null && result.getData() != null) {
                    return FastjsonUtil.getJsonDataOnFirst(result.getData(),cls);
                }
                return null;
            }
        }).subscribeOn(Schedulers.newThread());
    }


    //将服务器返回的数据转换为Map
    protected  Observable<Map<String,String>> turnOutMap(Observable<Result> observable) {
        return turnOutResult(observable).map(new Function<Result, Map<String,String>>() {
            @Override
            public Map<String,String> apply(Result result)  {
                if (result != null && result.getData() != null) {
                    return FastjsonUtil.toKV(result.getData());
                } else {
                    LogUtils.d(TAG, "apply() 返回数据为空: " + "");
                }
                return null;
            }
        }).subscribeOn(Schedulers.newThread());
    }

}
